import { Request } from 'express';
import { CanActivate, ExecutionContext, Injectable, UnauthorizedException } from '@nestjs/common';
import { JwtService } from '@nestjs/jwt';
import { ValidatePublic } from './validatePublic';

@Injectable()
export class AuthGuard implements CanActivate {
    constructor(
        private jwtService: JwtService,
        private readonly validatePublic: ValidatePublic
    ) {}

    async canActivate(context: ExecutionContext): Promise<boolean> {
        const isPublic = this.validatePublic.isPublic(context);
        if (isPublic) {
            return true;
        }

        const request = context.switchToHttp().getRequest();
        const token = this.extractToken(request);
        if (!token) {
            throw new UnauthorizedException();
        }

        try {
            const payload = await this.jwtService.verifyAsync(token, { secret: 'libai' });
            request['user'] = payload;
        } catch (err) {
            throw new UnauthorizedException();
        }

        return true;
    }

    private extractToken(request: Request): string | undefined {
        return this.extractTokenFromCookie(request) || this.extractTokenFromHeader(request);
    }

    private extractTokenFromHeader(request: Request): string | undefined {
        const [type, token] = request.headers?.authorization?.split(' ') ?? [];
        return type === 'Bearer' ? token : undefined;
    }

    private extractTokenFromCookie(request: Request): string | undefined {
        const [type, token] = request.cookies?.['Authorization']?.split(' ') ?? [];
        return type === 'Bearer' ? token : undefined;
    }
}
